<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
    <script>
        // 在js的语法中，分为两大类：直接写数据、写变量名
        // 这里容易让人混淆的是字符串和变量名，但凡加了引号都是字符串，不加而且写的不是数字和布尔，都是变量名
        // console.log(10) // 写死的打印10
        // let age = 19
        // console.log('age') // age
        // console.log(age) // 19

        // console.log(true)
        // console.log(你好) // 会报错，相当于找你好这个变量

        /*
            基本类型数据的==比较细节
                同类型之间直接比较值是否一致
                不同类型之间会进行隐式转换，都是转换成数字
        */

        // console.log('true' == true) // false
        /*
            'true'转成了NaN
            true 转成了1
            相当于判断 NaN == 1 所以得到false
        */
        // console.log('false' == false) // false
          /*
            'false'转成了NaN
            false 转成了0
            相当于判断 NaN == 0 所以得到false
        */
        // console.log('10' == 10) // true
        // console.log(1 == true) // true
        // console.log(0 == false) // true

        // console.log('10' == '10') // false


        // 复杂类型之间==是比较地址
        // 但凡遇到new 或者 [] 或者 {} 都会开辟新的堆空间
        // [] 其实相当于是new Array
        // {} 其实相当于是new Object
        // console.log( { name: 'jack', age: 16 } == { name: 'jack', age: 16 } ) // false
        // let obj1 = { name: 'jack', age: 16 }
        // let obj2 = obj1
        // console.log(obj1 == obj2) // true

        // console.log( {} == {} ) // false
        // console.log( [] == [] ) // false

        console.log( !{} == {} ) // false
        /*
            !做隐式转换，把右边转成布尔，再进行取反
                {}是对象，那么就是true，只有0、NaN、null、undefined、空字符串隐式转换成为false,其他都是true

            !{} 得到false
            现在相当于判断
              false == {}
            基本类型和复杂类型之间如何比较？
                会先把复杂类型调用toString或者调用valueOf(基本包装类型)先转成基本类型再按照基本类型的规则进行比较

              false == '[object Object]'
            基本类型的不同类型会转成数字
                0 == NaN  所以结果为false
        */
        console.log( ![] == [] ) // true
        /*
            ![] 得到false
            false == []
            false == ''
            0 == 0  得到true
        */


        // 什么叫基本包装类型
        // 方法和属性只有对象类型才有
        let age = 16
        let str = 'hello'
        // 那为什么基本类型可以调用方法和属性？
        // 原因是js为了方便大家操作数据，提供了三种复杂类型：Number String Boolean
        // 就是专门帮你把基本类型包装成对象类型，所以这三种复杂类型又叫基本包装类型
        console.log(age.toFixed(2))
        /*
            内部相当于帮你做了如下转换
            let num = new Number(age) // 相当于传入了16
            num.toFixed(2)
        */
        console.log(str.length)
        /*
            let str = new String(str)
            str.length
        */

        // 基本类型是没有方法和属性的
        // console.log(null.length)
        // console.log(undefined.length)

        // valueOf的方法：基本只存在于包装类型，也就是说只存在于Number、String、Boolean
        // valueOf这个方法可以得到这个包装类型对应的基本类型的值
        // let numObj = new Number('10')
        // console.log(numObj) // 对象
        // console.log(numObj.valueOf()) // 10


        // let strObj = new String(100)
        // console.log(strObj) // 对象
        // console.log(strObj.valueOf()) // '100'
    

        console.log(![] == new Boolean('a')) // false
        /*
            false == new Boolean('a')
                因为右边是基本包装类型会调用valueOf，会得到对应的基本类型值
            false == true 得到 false
        */
        console.log(![] == new Boolean('')) // true

        console.log(![] == new Number('0')) // true
        /*
            false == new Number('0') 相当于转数字就是0
            false == 0
            0 == 0
        */
    </script>
</body>
</html>